home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 January / macformat46.iso / Shareware Plus / Developers / ASTcl 1.0 / ASTcl-1.0 / ASTclUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-28  |  5.9 KB  |  256 lines

  1. /*
  2.  * ASTcl -- DoAppleScript package for MacTcl 7.5.1
  3.  * This code adds the command "DoAppleScript <script>" to MacTcl.
  4.  *
  5.  * ASTclUtils.c -- OSA utilities
  6.  * Adapted from "FinderScripter (Scripts)" 
  7.  * in Ultimate Mac Programming by Dave Mark.
  8.  * Written on 960927.
  9.  * 
  10.  * Copyright (c) 1996 by Theodore C. Belding
  11.  * University of Michigan Program for the Study of Complex Systems
  12.  * <mailto:Ted.Belding@umich.edu>
  13.  * <http://www-personal.engin.umich.edu>
  14.  * 
  15.  * This code is freeware.
  16.  */
  17.  
  18. #include <ASRegistry.h>            /* AppleScript constants */
  19. #include <AEPackObject.h>        /* object specifier building utilities */
  20. #include <OSAGeneric.h>
  21. #include <AppleScript.h>
  22. #include <string.h>
  23.  
  24. #include "ASTclUtils.h"
  25.  
  26. /* globals */
  27.  
  28. static ComponentInstance        gGenericSC; 
  29.  
  30.  
  31. /* fcn declarations */
  32.  
  33. int        OSAScriptInit( void );
  34. int        ProcessScript( char* scriptStr, char* result );
  35. static int        CompileScript( char* scriptStr, OSAID *scriptIDPtr, char* result);
  36. static int        ExecuteScript( OSAID scriptID, char* result );
  37. static int        GetScriptResults( OSAID resultID, char* result);
  38. static int        GetScriptError( char* result );
  39. static int        DescToString( AEDesc *textDescPtr, char* result );
  40.  
  41.  
  42. /* OSAScriptInit */
  43.  
  44. int    OSAScriptInit( void )
  45. {
  46.     OSAError    err;
  47.     
  48.     gGenericSC = OpenDefaultComponent( kOSAComponentType,
  49.                     kOSAGenericScriptingComponentSubtype );
  50.  
  51. /*    To target a script at a specific language, call OSASetDefaultScriptingComponent() and */
  52. /*    pass in the selector code for AppleScript, kAppleScriptSubtype, which is defined in AppleScript.h. */
  53. /*    By the way, if you want, you can save the old default scripting component */
  54. /*    (a la GetPort()) by calling OSAGetDefaultScriptingComponent()... */
  55.  
  56.     err = OSASetDefaultScriptingComponent( gGenericSC, kAppleScriptSubtype );
  57.     
  58.     if ( err != noErr ) 
  59.         return  1;
  60.     else
  61.         return 0;
  62. }
  63.  
  64. /* ProcessScript */
  65.  
  66. int    ProcessScript( char* scriptStr, char* result )
  67. /*    This routine is called to run the script in scriptStr. */
  68. {
  69.     OSAID        scriptID;
  70.  
  71.     scriptID = kOSANullScript;    /* Each time we start a new script we want to */
  72.                                 /* reinitialize the scriptID. If we are */
  73.                                 /* correcting a script that had a syntax error, */
  74.                                 /* we'll want to reuse the same scriptID... */
  75.     
  76.     if ( !CompileScript( scriptStr, &scriptID, result) )
  77.     {    /* script compiled okay */
  78.         if ( ExecuteScript( scriptID, result ) ) {
  79.             strcpy(result, "Error executing script");
  80.             return 1;
  81.         }
  82.         else 
  83.             return 0;
  84.     }
  85.     else {
  86.         strcpy(result, "Error compiling script");
  87.         return 1;
  88.     }
  89.     
  90. }
  91.  
  92. /* CompileScript */
  93.  
  94. static int        CompileScript( char* scriptStr, OSAID *scriptIDPtr, char* result )
  95. {
  96.     OSErr        err;
  97.     OSAError    errOSA;
  98.     AEDesc        errorDesc = {typeNull, NULL};
  99.     AEDesc        textDesc = {typeNull, NULL};
  100.     
  101.     err = AECreateDesc( typeChar, scriptStr, strlen(scriptStr), &textDesc );
  102.     
  103.     if ( err != noErr ) {
  104.         strcpy(result, "Error calling AECreateDesc()");
  105.         return 1;
  106.     }
  107.  
  108.     errOSA = OSACompile( gGenericSC, &textDesc, kOSAModeNull, scriptIDPtr );
  109.     
  110.     err = AEDisposeDesc( &textDesc );
  111.     
  112.     if ( err != noErr ) {
  113.         strcpy(result, "Error calling AEDisposeDesc()");
  114.         return 1;
  115.     }
  116.     
  117.     if ( errOSA == errOSAScriptError )
  118.     {
  119.         GetScriptError( result );
  120.         return 1;
  121.     }
  122.     else if ( errOSA != noErr ) {
  123.         strcpy(result, "Error calling OSACompile()");
  124.         return 1;
  125.     }
  126.     
  127.     /* compiled successfully */
  128.     return 0;
  129. }
  130.  
  131.  
  132. /* ExecuteScript */
  133.  
  134. static int    ExecuteScript( OSAID scriptID, char* result )
  135. {
  136.     OSAID        resultID;
  137.     OSAError    errOSA;
  138.     AEDesc        errorDesc = {typeNull, NULL};
  139.     
  140.     errOSA = OSAExecute( gGenericSC, scriptID, kOSANullScript,
  141.                 kOSAModeNull, &resultID );
  142.     
  143.     if ( errOSA == errOSAScriptError )
  144.     {
  145.         GetScriptError( result );
  146.         return 1;
  147.     }
  148.     else if ( errOSA != noErr ) {
  149.         strcpy(result, "Error calling OSAExecute()");
  150.         return 1;
  151.     }
  152.  
  153. /*    If we get here, the script executed successfully. */
  154. /*    Now we'll get the result... */
  155.     
  156.     return GetScriptResults( resultID, result );
  157. }
  158.  
  159.  
  160. /* DisplayScriptResults */
  161.  
  162. static int    GetScriptResults( OSAID resultID, char* result)
  163. {
  164.     OSAError    errOSA;
  165.     OSErr        err;
  166.     AEDesc        resultDesc = {typeNull, NULL};
  167.  
  168. /*    OSADisplay() takes the resultID and builds a typeChar descriptor */
  169. /*    containing a human-readable description of the results. */
  170.     errOSA = OSADisplay( gGenericSC, resultID, typeChar,
  171.                 kOSAModeDisplayForHumans, &resultDesc );
  172.  
  173. /*    OSADisplay() will return an error if you attempt to display */
  174. /*    the undisplayable. For example, if your script toggles the */
  175. /*    "warn before emptying" check box, you won't have anything */
  176. /*    useful to display. We'll put up a message if we get an error... */
  177.     if ( errOSA != noErr ) {
  178.         strcpy(result, "Error calling OSADisplay()");
  179.         return 1;
  180.     }
  181.     else
  182.     {
  183. /*    If the call to OSADisplay() was successful, we'll */
  184. /*    convert the descriptor to a string. */
  185.         DescToString( &resultDesc, result );
  186.         
  187.         err = AEDisposeDesc( &resultDesc );
  188.         
  189.         if ( err != noErr ) {
  190.             strcpy(result, "Error calling AEDisposeDesc()");
  191.             return 1;
  192.         }
  193.         else {
  194.             return 0;
  195.         }
  196.     }
  197. }
  198.  
  199.  
  200. /* ReportScriptError */
  201.  
  202. static int    GetScriptError( char* result )
  203. {
  204.     OSAError    errOSA;
  205.     OSErr        err;
  206.     AEDesc        errorDesc = {typeNull, NULL};
  207.  
  208. /*    Retrieve the error message from OSAScriptError() and */
  209. /*    display the message... */
  210.     errOSA = OSAScriptError( gGenericSC, kOSAErrorMessage,
  211.                     typeChar, &errorDesc );
  212.     
  213.     if ( errOSA != noErr ) {
  214.         strcpy(result, "Error calling OSAScriptError()");
  215.         return 1;
  216.     }
  217.     DescToString( &errorDesc, result );
  218.         
  219.     err = AEDisposeDesc( &errorDesc );
  220.     
  221.     if ( err != noErr ) {
  222.         strcpy(result, "Error calling AEDisposeDesc()");
  223.         return 1;
  224.     }
  225.     else {
  226.         return 0;
  227.     }
  228. }
  229.  
  230.  
  231. /* DescToString */
  232.  
  233. static int    DescToString( AEDesc *textDescPtr, char* result)
  234. {
  235.     Size len;
  236.     
  237.     if ( textDescPtr->descriptorType != typeChar ) {
  238.         strcpy(result, "Tried to convert a non-typeChar descriptor to a string!!!");
  239.         return 1;
  240.     }
  241.     
  242.     len = GetHandleSize(textDescPtr->dataHandle);
  243.     
  244.     HLock( textDescPtr->dataHandle );
  245.     
  246.     strncpy(result, *(textDescPtr->dataHandle), (unsigned int) len);
  247.     
  248.     HUnlock( textDescPtr->dataHandle );
  249.     
  250.     result[(unsigned int) len] = '\0';
  251.     
  252.     return 0;
  253. }
  254.  
  255.  
  256.